package org.crh.payment.impl;

import org.crh.common.ProviderFeignClient;
import org.crh.common.ScheduleService;
import org.crh.common.domain.AppointmentRecord;
import org.crh.common.response.impl.RuntimeResponse;
import org.crh.payment.PaymentChannelService;
import org.crh.payment.PaymentService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.crh.payment.domain.PaymentReq;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;


/**
 * @description:
 * @author: RenHai Chen
 * @date: 2025/3/31 10:36
 */

@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    PaymentChannelService paymentChannelService;

    @Autowired
    private ProviderFeignClient providerFeignClient;

    @Autowired
    private ScheduleService scheduleService;

    private RedissonClient redissonClient;

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private String redisPort;

    @Value("${spring.redis.password:}")
    private String password;

    @PostConstruct
    public void init() {
        //1.构造redisson实现分布式锁必要的Config
        Config config = new Config();
        String redisadress="redis://"+redisHost+":"+redisPort;
        config.useSingleServer().setAddress(redisadress);
        config.useSingleServer().setPassword(password);
        // 2.构造RedissonClient
        redissonClient = Redisson.create(config);

    }

    @GlobalTransactional
    @Override
    public ResponseEntity<RuntimeResponse> processPayment(PaymentReq paymentReq) {
        // 1. 校验订单状态
        AppointmentRecord order = providerFeignClient.getOrderByOrderNo(paymentReq.getOrderNo());
        if (order.getStatus() != 0) {
            return ResponseEntity.ok(new RuntimeResponse(500, "订单状态异常"));
        }

        // 2. 调用支付渠道
        boolean paySuccess = paymentChannelService.pay(paymentReq);

        if (paySuccess) {
            // 3. 扣减数据库库存（乐观锁）
            int effectRows = scheduleService.reduceStock(
                    order.getSlotId(),
                    1,
                    order.getVersion()
            );
            if (effectRows == 0) {
                // 触发库存补偿
                rocketMQTemplate.send(
                        "STOCK_COMPENSATE_TOPIC",
                        MessageBuilder.withPayload(order).build()
                );
                return ResponseEntity.ok(new RuntimeResponse(500, "库存扣减失败"));
            }

            // 4. 更新订单状态
            order.setStatus(1);
            providerFeignClient.updateStatus(order);

            // 5. 发送支付成功事件
            rocketMQTemplate.convertAndSend("PAY_SUCCESS_TOPIC", order);
            return ResponseEntity.ok(new RuntimeResponse(200, "支付成功"));
        }

        // 支付失败恢复Redis库存
        String key =String.valueOf(order.getSlotId());
        RBucket<String> bucket = redissonClient.getBucket(key);
        Integer redisStock =Integer.valueOf(bucket.get());
        bucket.set(String.valueOf(redisStock+1));
        return ResponseEntity.ok(new RuntimeResponse(500, "支付失败"));
    }
}


